package com.yzdmw.toutiao.login.data;

import com.yzdmw.toutiao.R;
import com.yzdmw.toutiao.model.LoggedInUser;
import com.yzdmw.toutiao.model.Response;
import com.yzdmw.toutiao.service.NetworkService;
import com.yzdmw.toutiao.service.UserService;

import io.reactivex.rxjava3.core.Observable;

/**
 * Class that requests authentication and user information from the remote data source and
 * maintains an in-memory cache of login status and user credentials information.
 */
public class LoginRepository {

    private static volatile LoginRepository instance;
    private final UserService userService;
    private String token;
    private LoggedInUser user = null;

    private LoginRepository() {
        this.userService = NetworkService.getInstance().getUserService();
    }

    public static LoginRepository getInstance() {
        if (instance == null) {
            instance = new LoginRepository();
        }
        return instance;
    }

    public boolean isLoggedIn() {
        return token != null && user != null;
    }

    public Observable<Response<LoggedInUser>> login(String username, String password){
        return userService.login(username,password)
                .onErrorReturn(err-> new Response<>(false, R.string.internal_server_error, null))
                .doOnNext(response -> {
                    if (response.success && response.code == 200)
                        token = (String) response.data;
                })
                .flatMap(response -> {
                    if (response.success && response.code == 200)
                        return userService.getUserInfo(username,response.data);
                    else
                        return Observable.just(
                                new Response<LoggedInUser>(false, R.string.login_failed,null));
                })
                .doOnNext(result -> {
                    if (result.success && result.data != null) {
                        this.user = result.data;
                    }
                });
    }
    public Observable<Response<String>> logout(){
        if (token != null && user != null) {
            user = null;
            return userService.logout(token)
                    .onErrorReturn(err-> new Response<>(false, R.string.internal_server_error, null))
                    .doOnNext(response -> {
                        if (response.success && response.code == 200) // 确认无效了才丢弃token
                            token = null;
                    });
        } else
            return Observable.just(new Response<>(true, 200, null));
    }
    public Observable<Response<LoggedInUser>> info(String username){
        if (user != null)
            return Observable.just(new Response<>(true, 200, user));
        else
            return Observable.just(new Response<>(false, R.string.login_failed, null));
    }

    public Observable<Response<LoggedInUser>> regist(String username, String password) {
        return userService.regist(username,password)
                .onErrorReturn(err-> new Response<>(false, R.string.internal_server_error, null))
                .flatMap( response -> {
                    if (response.success && response.code == 200)
                        return login(username,password);
                    else
                        return Observable.just(
                                new Response<>(false, R.string.login_failed, null));
                });
    }
}